package Serialization;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;

import Carte.Calendrier;
import Carte.Trajet;
import Carte.Ville;
import Client.Reservation;
import Passager.Passager;
import Passager.Profil;
import Serveur.Serveur;
import Services.Repas;
import Services.ServiceChoisis;
import Services.TypeClasseTransport;
import Services.typeBillet;
import Transports.Avion;
import Transports.Bateau;
import Transports.Bus;
import Transports.Train;
import Transports.Transports;
import Transports.TypeTransport;

public class SerialisationText extends Serialisation{
	private static final String FICHIER_LISTE_TRANSPORT = "listeTransport.txt";
	private static final String FICHIER_LISTE_TRAJET = "listeTrajet.txt";
	private static final String FICHIER_LISTE_RESERVATION = "listeReservation.txt";
	private static final String FICHIER_LISTE_PASSAGER = "listePassager.txt";
	private RandomAccessFile fichierTransport;
	private RandomAccessFile fichierTrajet;
	private RandomAccessFile fichierReservation;
	private RandomAccessFile fichierPassager;

	public static final String CAR_SPACE = "/";
	public static final String CAR_REPLACE = "_";
	public static final String CAR_SPACE2 = ";";
	public static final String CAR_SPACE3 = ":";
	public static final String CAR_SPACE4 = ",";
	
	public SerialisationText(Serveur serv) {
		super(serv);
		initialisation();
	}

	/**
	 * sauvegarde tout les transports/trajets/reservations dans les fichiers
	 * 
	 * @param ListeTransport
	 * @param ListeTrajet
	 * @param ListeReservation
	 * @return
	 */
	public void serializeListe(ArrayList<Transports> ListeTransport,
			ArrayList<Trajet> ListeTrajet,
			ArrayList<Reservation> ListeReservation,
			ArrayList<Passager> ListePassager) {
		// on ecrit la liste des transports:
		// pour chaque transport on ecrit
		// nomTransport/descriptionTransport/capacitéTransport
		sup();
		initialisation();
		try {
			for (int i = 0; i < ListeTransport.size(); i++) {
				fichierTransport.writeBytes(ecrireTransport(ListeTransport.get(i)));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			for (int i = 0; i < ListeTrajet.size(); i++) {
				fichierTrajet.writeBytes(ecrireTrajet(ListeTrajet.get(i)) + "\n");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			for (int i = 0; i < ListeReservation.size(); i++) {
				fichierReservation.writeBytes(ecrireReservation(ListeReservation
						.get(i))
						+ "\n");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			for (int i = 0; i < ListePassager.size(); i++) {
				fichierPassager.writeBytes(ecrirePassager(ListePassager
						.get(i))
						+ "\n");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * supprimer les fichiers pour ne pas reecrire dessus
	 * 
	 * @param return
	 */
	public void sup() {
		File monFichier = new File(FICHIER_LISTE_TRANSPORT);
		if (monFichier.exists()) {
			monFichier.delete();
		}
		File monFichier2 = new File(FICHIER_LISTE_TRAJET);
		if (monFichier2.exists()) {
			monFichier2.delete();
		}
		File monFichier3 = new File(FICHIER_LISTE_RESERVATION);
		if (!monFichier3.exists()) {
			monFichier3.delete();
		}
		File monFichier4 = new File(FICHIER_LISTE_PASSAGER);
		if (!monFichier4.exists()) {
			monFichier4.delete();
		}
	}

	/**
	 * initialise les lectures/ecritures fichiers
	 * 
	 * @param return
	 */
	public void initialisation() {
		try {
			fichierTransport = new RandomAccessFile(FICHIER_LISTE_TRANSPORT,
			"rw");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("Impossible d'ouvrir le fichier "
					+ FICHIER_LISTE_TRANSPORT);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fichierTrajet = new RandomAccessFile(FICHIER_LISTE_TRAJET, "rw");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("Impossible d'ouvrir le fichier "
					+ FICHIER_LISTE_TRAJET);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fichierReservation = new RandomAccessFile(FICHIER_LISTE_RESERVATION, "rw");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("Impossible d'ouvrir le fichier "
					+ FICHIER_LISTE_RESERVATION);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fichierPassager = new RandomAccessFile(FICHIER_LISTE_PASSAGER, "rw");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("Impossible d'ouvrir le fichier "
					+ FICHIER_LISTE_PASSAGER);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * ferme les fichiers et appel les methodes pour sauvegarder les donnees
	 * 
	 * @param ListeTransport
	 * @param ListeTrajet
	 * @param ListeReservation
	 *            return
	 */
	public void close(ArrayList<Transports> ListeTransport,
			ArrayList<Trajet> ListeTrajet,
			ArrayList<Reservation> ListeReservation, ArrayList<Passager> ListePassager) {
		sup();
		initialisation();
		// on ecrit la liste des transport, trajet, reservation et on ferme les
		// fichiers
		serializeListe(ListeTransport, ListeTrajet, ListeReservation, ListePassager);
		try {
			fichierTransport.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			fichierTrajet.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			fichierReservation.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			fichierPassager.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * ecrit la date en bon format pour etre sauvegarde
	 * 
	 * @param Date
	 *            d return String
	 */
	private String ecrireDate(GregorianCalendar d) {
		return (d.get(GregorianCalendar.YEAR) + CAR_SPACE + d.get(GregorianCalendar.MONTH) + CAR_SPACE + d.get(GregorianCalendar.DAY_OF_MONTH)
				+ CAR_SPACE + d.get(GregorianCalendar.HOUR_OF_DAY) + CAR_SPACE + d.get(GregorianCalendar.MINUTE));
	}

	/**
	 * ecrit une liste de int
	 * @param listeInteger
	 * @return
	 */
	private String ecrireListeInteger(ArrayList<Integer> listeInteger){
		String str = "";

		for(int i=0; i<listeInteger.size(); i++){
			if(i != listeInteger.size()-1){
				str += listeInteger.get(i) + CAR_SPACE2;
			}
			else str += listeInteger.get(i);
		}
		return str;
	}

	/**
	 * ecrit une liste de repas
	 * @param listeRepas
	 * @return
	 */
	private String ecrireListeRepas(ArrayList<Repas> listeRepas){
		String str = "";

		for(int i=0; i<listeRepas.size(); i++){
			if(i != listeRepas.size()-1){
				str += listeRepas.get(i) + CAR_SPACE4;
			}
			else str += listeRepas.get(i);
		}
		return str;
	}

	/**
	 * ecrit une liste de servicechoisis
	 * @param sc
	 * @return
	 */
	private String ecrireListeServiceChoisis(ArrayList<ServiceChoisis> listeSC){
		String str = "";

		for(int i=0; i<listeSC.size(); i++){
			if(i != listeSC.size()-1){
				str += ecrireUnServiceChoisis(listeSC.get(i)) + CAR_SPACE2;
			}
			else str += ecrireUnServiceChoisis(listeSC.get(i));
		}
		return str;		
	}

	private String ecrireUnServiceChoisis(ServiceChoisis sc){
		String str = sc.getClasseDuTransport() + CAR_SPACE3 + sc.getProfilUtilisateur() + CAR_SPACE3;
		str += ecrireListeRepas(sc.getRepas()) + CAR_SPACE3 + sc.getBillet() + CAR_SPACE3 + sc.getNbNuite();
		return str;		
	}
	/**
	 * ecrit un transport en bon format pour etre sauvegarde
	 * 
	 * @param Transport
	 *            t return String
	 */
	private String ecrireTransport(Transports t) {
		return (t.getIdTransport() + CAR_SPACE + t.getTypeDuTransport()  + CAR_SPACE
				+ t.getPrixBillet()+ CAR_SPACE + t.getCapacite() + "\n");
	}

	/**
	 * ecrit un trajet en bon format pour etre sauvegarde
	 * 
	 * @param Trajet
	 * @return String
	 */
	private String ecrireTrajet(Trajet t) {
		return (t.getVilleDepart().getVille() + CAR_SPACE
				+ t.getVilleArrive().getVille() + CAR_SPACE
				+ ecrireDate(t.getDatedepart())
				+ CAR_SPACE + ecrireDate(t.getDatearrive())
				+ CAR_SPACE + t.getIdTransport() + CAR_SPACE + t.getDistance() + CAR_SPACE + t.getIDTrajet());
	}

	/**
	 * Ecrit une Reservation au bon format pour etre sauvegarder
	 * @param t
	 * @return String
	 */

	private String ecrireReservation(Reservation t) {
		String str = t.getIdReservation() + CAR_SPACE + t.getIdTrajet() + CAR_SPACE;
		str += ecrireDate(t.getDate()) + CAR_SPACE;
		str += t.getNbPersonne() + CAR_SPACE + ecrireListeInteger(t.getListePassager()) + CAR_SPACE;
		str += ecrireListeServiceChoisis(t.getListeServiceChoisi());
		return str;
	}

	/**
	 * Ecrit un Passager au bon format pour etre sauvegarder
	 * @param p un passager
	 * @return une chaine de charactere a ecrire dans le fichier
	 */
	private String ecrirePassager(Passager p)
	{
		return (p.getIdPassager() + CAR_SPACE + p.getNom() + CAR_SPACE + p.getPrenom());
	}

	/**
	 * Recupere tout les transports contenue dans le fichier et les rend sous
	 * forme de liste
	 * 
	 * @param
	 * @return ArrayList<Transport>
	 */
	public ArrayList<Transports> fillOutListeTransport() {
		
		// methode pour recuperer une liste de transport contenue dans un
		// fichier
		ArrayList<Transports> ListeTransport = new ArrayList<Transports>();
		
		String ligneFichier;
		String[] params;
		Transports temp = null;
		try {
			while ((ligneFichier = fichierTransport.readLine()) != null) {
				// tant que l'on peut lire une ligne dans le fichier on
				// recupere cette ligne on la decoupe par
				// rapport au CAR_SPACE et on l'enregistre dans un tableau
				params = ligneFichier.split(CAR_SPACE);
				
				//Tranformer le string en enum
				//
				TypeTransport type = TypeTransport.toProfil(params[1]);
				
				//Selon le type de transport
				//
				switch(type){
					case AVION:
						temp = new Avion(serv, Integer.parseInt(params[0]), Double.parseDouble(params[2]), Integer.parseInt(params[3]));
						break;
					case BATEAU:
						temp = new Bateau(serv, Integer.parseInt(params[0]), Double.parseDouble(params[2]), Integer.parseInt(params[3]));
						break;
					case BUS:
						temp = new Bus(serv, Integer.parseInt(params[0]), Double.parseDouble(params[2]), Integer.parseInt(params[3]));
						break;
					case TRAIN:
						temp = new Train(serv, Integer.parseInt(params[0]), Double.parseDouble(params[2]), Integer.parseInt(params[3]));
						break;
				}
				
				// Ajouter les elements dans la liste
				//
				ListeTransport.add(temp);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return ListeTransport;
	}

	/**
	 * Recupere tout les trajets contenue dans le fichier et les rend sous forme
	 * de liste
	 * 
	 * @param
	 * @return ArrayList<Trajet>
	 */
	public ArrayList<Trajet> fillOutListeTrajet() {
		// methode pour recuperer une liste de transport contenue dans un
		// fichier
		ArrayList<Trajet> ListeTrajet = new ArrayList<Trajet>();
		String ligneFichier;
		String[] params;
		Trajet temp;
		try {
			while ((ligneFichier = fichierTrajet.readLine()) != null) {
				// tant que l'on peut lire une ligne dans le fichier on
				// recupere cette ligne on la decoupe par
				// rapport au CAR_SPACE et on l'enregistre dans un tableau
				params = ligneFichier.split(CAR_SPACE);
				
				// on creer un transport avec les informations receuillies
				temp = new Trajet(serv,Ville.toVille(params[0]), Ville.toVille(params[1]),
						new GregorianCalendar(Integer.parseInt(params[2]),Integer.parseInt(params[3]),
								Integer.parseInt(params[4]), Integer.parseInt(params[5]),
								Integer.parseInt(params[6])),
								new GregorianCalendar(Integer.parseInt(params[7]),Integer.parseInt(params[8]),
										Integer.parseInt(params[9]),Integer.parseInt(params[10]),
										Integer.parseInt(params[11])),
										Integer.parseInt(params[12]),
										Integer.parseInt(params[13]),
										Integer.parseInt(params[14]));
				
				// que l'on ajoutera dans la liste des transport
				ListeTrajet.add(temp);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return ListeTrajet;
	}

	/**
	 * Recupere toute les reservations contenue dans le fichier et les rend sous
	 * forme de liste
	 * 
	 * @param
	 * @return ArrayList<Reservation>
	 */
	public ArrayList<Reservation> fillOutListeReservation() {
		// methode pour recuperer une liste de reservation contenue dans un
		// fichier
		ArrayList<Reservation> listeReservation = new ArrayList<Reservation>();
		String ligneFichier;
		String[] params;
		String[] params2;
		String[] params3;
		String[] params4;
		String[] params5;
		Reservation temp = null;
		try {
			while ((ligneFichier = fichierReservation.readLine()) != null) {
				// temps que l'on peut lire une ligne dans le fichier on
				// recupere cette ligne on la decoupe par
				// rapport au CAR_SPACE et on l'enregistre dans un tableau
				params = ligneFichier.split(CAR_SPACE);
				// on creer une reservation avec les information receuilli
				
				int IDReservation = Integer.parseInt(params[0]);
				int IDTrajet = Integer.parseInt(params[1]);
				
				GregorianCalendar  gc = new GregorianCalendar(Integer.parseInt(params[2]),
						Integer.parseInt(params[3]),Integer.parseInt(params[4]), 
						Integer.parseInt(params[5]),Integer.parseInt(params[6]));
				
				int nbPersonnes = Integer.parseInt(params[7]);
				
				//Recréer la liste des passagers
				ArrayList <Integer> listePassager = new ArrayList<Integer>();
				params2 = params[8].split(CAR_SPACE2);
				for(int i=0; i< params2.length; i++){
					listePassager.add(Integer.parseInt(params2[i]));
				}
				
				//Recréer la liste des services choisis
				ArrayList<ServiceChoisis> listeServiceChoisis = new ArrayList<ServiceChoisis>();
				params3 = params[9].split(CAR_SPACE2);
				//params3.length correspond au nombre de services choisis a recreer
				for(int j=0; j<params3.length; j++){
					//On découpe pour avoir un service(qui est maintenant dans params4)
					params4 = params3[j].split(CAR_SPACE3);
					
					//On recrée la liste des repas de ce service
					params5 = params4[2].split(CAR_SPACE4);
					ArrayList<Repas> repas = new ArrayList<Repas>();
					for(int k=0; k<params5.length; k++){
						repas.add(Repas.toRepas(params5[k]));
					}
					listeServiceChoisis.add(new ServiceChoisis(TypeClasseTransport.toProfil(params4[0]), Profil.toProfil(params4[1]), repas, typeBillet.toProfil(params4[3]), Integer.parseInt(params4[4])));
				}
				
				
				temp = new Reservation(serv, IDTrajet, listePassager, listeServiceChoisis, IDReservation, gc);
						
				// que l'on ajoutera dans la liste des reservation
				listeReservation.add(temp);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return listeReservation;
	}

	/**
	 * Recupere tout les passager contenue dans le fichier et les rend sous
	 * forme de liste
	 * @return ArrayList<Passager>
	 */
	public ArrayList<Passager> fillOutListePassager(){
		// methode pour recuperer une liste de passager contenue dans un
		// fichier
		ArrayList<Passager> ListePassager= new ArrayList<Passager>();
		String ligneFichier;
		String[] params;
		Passager temp = null;
		try {
			while ((ligneFichier = fichierPassager.readLine()) != null) {
				// tant que l'on peut lire une ligne dans le fichier on
				// recupere cette ligne on la decoupe par
				// rapport au CAR_SPACE et on l'enregistre dans un tableau
				params = ligneFichier.split(CAR_SPACE);
				// on creer un passager avec les information receuilli
				
				temp = new Passager(serv, Integer.parseInt(params[0]), params[1], params[2]);
				// que l'on ajoutera dans la liste des passagers
				
				ListePassager.add(temp);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return ListePassager;
	}
}
